const Queue = require("./Lx_queue");

class Graph {
    constructor() {
        this.vertexes = [];
        this.edges = new Map();
    }

    addVertexes(v) {
        this.vertexes.push(v);
        this.edges.set(v, []);
    }

    addEdge(v1, v2) {
        this.edges.get(v1).push(v2);
        this.edges.get(v2).push(v1);
    }

    toString() {
        let str = "";
        this.vertexes.forEach((vertexe) => {
            str += vertexe + "=>" + this.edges.get(vertexe).toString() + ",";
        });
        return str;
    }

    initializeColor() {
        let colors = {};
        this.vertexes.forEach((item) => (colors[item] = "white"));
        return colors;
    }

    bfs(initV, handler) {
        const colors = this.initializeColor();
        var queue = new Queue();
        queue.enqueue(initV);
        while (!queue.isEmpty()) {
            var v = queue.dequeue();
            colors[v] = "grey";
            var vList = this.edges.get(v);
            vList.forEach((vItem) => {
                if (colors[vItem] == "white") {
                    colors[vItem] = "gray";
                    queue.enqueue(vItem);
                }
            });
            handler(v);
            colors[v] = "black";
        }
    }

    dfs(v, handler) {
        var colors = this.initializeColor();
        this.dfsVisit(v, colors, handler);
    }

    dfsVisit(v, colors, handler) {
        colors[v] = "grey";
        const vList = this.edges.get(v);
        handler(v);

        vList.forEach((item) => {
            if (colors[item] == "white") {
                this.dfsVisit(item, colors, handler);
            }
        });
        colors[v] = "black";
    }
}

let lx_graph = new Graph();
var vertexstes = ["A", "B", "C"];
vertexstes.forEach((item) => lx_graph.addVertexes(item));
lx_graph.addEdge("A", "B");
lx_graph.addEdge("C", "B");
lx_graph.addEdge("C", "A");
console.log(lx_graph.toString());
lx_graph.bfs("A", (a) => {
    console.log(a);
});

lx_graph.dfs("A", (a) => {
    console.log(a);
});
